home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Development
/
Source
/
POVSRC
/
SOURCE
/
BOXES.C
< prev
next >
Wrap
Text File
|
1993-10-13
|
10KB
|
418 lines
/****************************************************************************
* boxes.c
*
* This module implements the box primitive.
* This file was written by Alexander Enzmann. He wrote the code for
* boxes and generously provided us these enhancements.
*
* from Persistence of Vision Raytracer
* Copyright 1993 Persistence of Vision Team
*---------------------------------------------------------------------------
* NOTICE: This source code file is provided so that users may experiment
* with enhancements to POV-Ray and to port the software to platforms other
* than those supported by the POV-Ray Team. There are strict rules under
* which you are permitted to use this file. The rules are in the file
* named POVLEGAL.DOC which should be distributed with this file. If
* POVLEGAL.DOC is not available or for more info please contact the POV-Ray
* Team Coordinator by leaving a message in CompuServe's Graphics Developer's
* Forum. The latest version of POV-Ray may be found there as well.
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
*****************************************************************************/
#include "frame.h"
#include "vector.h"
#include "povproto.h"
METHODS Box_Methods =
{
All_Box_Intersections,
Inside_Box, Box_Normal,
Copy_Box, Translate_Box, Rotate_Box, Scale_Box, Transform_Box,
Invert_Box, Destroy_Box
};
extern long Ray_Box_Tests, Ray_Box_Tests_Succeeded;
#define close(x, y) (fabs(x-y) < EPSILON ? 1 : 0)
int All_Box_Intersections (Object, Ray, Depth_Stack)
OBJECT *Object;
RAY *Ray;
ISTACK *Depth_Stack;
{
DBL Depth1, Depth2;
VECTOR IPoint;
register int Intersection_Found;
Intersection_Found = FALSE;
if (Intersect_Boxx (Ray, (BOX *)Object, &Depth1, &Depth2))
{
VScale (IPoint, Ray->Direction, Depth1);
VAddEq (IPoint, Ray->Initial);
if (Point_In_Clip (&IPoint, Object->Clip))
{
push_entry(Depth1,IPoint,Object,Depth_Stack);
Intersection_Found = TRUE;
}
if (Depth2 != Depth1)
{
VScale (IPoint, Ray->Direction, Depth2);
VAddEq (IPoint, Ray->Initial);
if (Point_In_Clip (&IPoint, Object->Clip))
{
push_entry(Depth2,IPoint,Object,Depth_Stack);
Intersection_Found = TRUE;
}
}
}
return (Intersection_Found);
}
int Intersect_Boxx (Ray, box, Depth1, Depth2)
RAY *Ray;
BOX *box;
DBL *Depth1, *Depth2;
{
DBL t, tmin, tmax;
VECTOR P, D;
Ray_Box_Tests++;
/* Transform the point into the boxes space */
if (box->Trans != NULL)
{
MInvTransPoint(&P, &Ray->Initial, box->Trans);
MInvTransDirection(&D, &Ray->Direction, box->Trans);
}
else
{
P.x = Ray->Initial.x;
P.y = Ray->Initial.y;
P.z = Ray->Initial.z;
D.x = Ray->Direction.x;
D.y = Ray->Direction.y;
D.z = Ray->Direction.z;
}
tmin = 0.0;
tmax = HUGE_VAL;
/* Sides first */
if (D.x < -EPSILON)
{
t = (box->bounds[0].x - P.x) / D.x;
if (t < tmin)
return 0;
if (t <= tmax)
tmax = t;
t = (box->bounds[1].x - P.x) / D.x;
if (t >= tmin)
{
if (t > tmax)
return 0;
tmin = t;
}
}
else if (D.x > EPSILON)
{
t = (box->bounds[1].x - P.x) / D.x;
if (t < tmin)
return 0;
if (t <= tmax)
tmax = t;
t = (box->bounds[0].x - P.x) / D.x;
if (t >= tmin)
{
if (t > tmax)
return 0;
tmin = t;
}
}
else if (P.x < box->bounds[0].x || P.x > box->bounds[1].x)
return 0;
/* Check Top/Bottom */
if (D.y < -EPSILON)
{
t = (box->bounds[0].y - P.y) / D.y;
if (t < tmin)
return 0;
if (t <= tmax)
tmax = t;
t = (box->bounds[1].y - P.y) / D.y;
if (t >= tmin)
{
if (t > tmax)
return 0;
tmin = t;
}
}
else if (D.y > EPSILON)
{
t = (box->bounds[1].y - P.y) / D.y;
if (t < tmin)
return 0;
if (t <= tmax)
tmax = t;
t = (box->bounds[0].y - P.y) / D.y;
if (t >= tmin)
{
if (t > tmax)
return 0;
tmin = t;
}
}
else if (P.y < box->bounds[0].y || P.y > box->bounds[1].y)
return 0;
/* Now front/back */
if (D.z < -EPSILON)
{
t = (box->bounds[0].z - P.z) / D.z;
if (t < tmin)
return 0;
if (t <= tmax)
tmax = t;
t = (box->bounds[1].z - P.z) / D.z;
if (t >= tmin)
{
if (t > tmax)
return 0;
tmin = t;
}
}
else if (D.z > EPSILON)
{
t = (box->bounds[1].z - P.z) / D.z;
if (t < tmin)
return 0;
if (t <= tmax)
tmax = t;
t = (box->bounds[0].z - P.z) / D.z;
if (t >= tmin)
{
if (t > tmax)
return 0;
tmin = t;
}
}
else if (P.z < box->bounds[0].z || P.z > box->bounds[1].z)
return 0;
*Depth1 = tmin;
*Depth2 = tmax;
/* printf("Box intersects: %g, %g\n", *Depth1, *Depth2); */
if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
return (FALSE);
else
*Depth1 = *Depth2;
else
if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
*Depth2 = *Depth1;
Ray_Box_Tests_Succeeded++;
return (TRUE);
}
int Inside_Box (IPoint, Object)
VECTOR *IPoint;
OBJECT *Object;
{
VECTOR New_Point;
BOX *box = (BOX *) Object;
/* Transform the point into the boxes space */
if (box->Trans != NULL)
MInvTransPoint(&New_Point, IPoint, box->Trans);
else
New_Point = *IPoint;
/* Test to see if we are inside the box */
if (New_Point.x < box->bounds[0].x || New_Point.x > box->bounds[1].x)
return ((int) box->Inverted);
if (New_Point.y < box->bounds[0].y || New_Point.y > box->bounds[1].y)
return ((int) box->Inverted);
if (New_Point.z < box->bounds[0].z || New_Point.z > box->bounds[1].z)
return ((int)box->Inverted);
/* Inside the box */
return 1-box->Inverted;
}
void Box_Normal (Result, Object, IPoint)
OBJECT *Object;
VECTOR *Result, *IPoint;
{
VECTOR New_Point;
BOX *box = (BOX *) Object;
/* Transform the point into the boxes space */
if (box->Trans != NULL)
MInvTransPoint(&New_Point, IPoint, box->Trans);
else
{
New_Point.x = IPoint->x;
New_Point.y = IPoint->y;
New_Point.z = IPoint->z;
}
Result->x = 0.0; Result->y = 0.0; Result->z = 0.0;
if (close(New_Point.x, box->bounds[1].x))
Result->x = 1.0;
else if (close(New_Point.x, box->bounds[0].x))
Result->x = -1.0;
else if (close(New_Point.y, box->bounds[1].y))
Result->y = 1.0;
else if (close(New_Point.y, box->bounds[0].y))
Result->y = -1.0;
else if (close(New_Point.z, box->bounds[1].z))
Result->z = 1.0;
else if (close(New_Point.z, box->bounds[0].z))
Result->z = -1.0;
else
{
/* Bad result, should we do something with it? */
Result->x = 1.0;
}
/* Transform the point into the boxes space */
if (box->Trans != NULL)
{
MTransNormal(Result, Result, box->Trans);
VNormalize(*Result, *Result);
}
}
void *Copy_Box (Object)
OBJECT *Object;
{
BOX *New;
New = Create_Box();
*New = *((BOX *) Object);
New->Trans = Copy_Transform(((BOX *)Object)->Trans);
return (New);
}
void Translate_Box (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
TRANSFORM Trans;
if (((BOX *)Object)->Trans == NULL)
{
VAddEq(((BOX *)Object)->bounds[0], *Vector);
VAddEq(((BOX *)Object)->bounds[1], *Vector);
Object->Bounds.Lower_Left = ((BOX *)Object)->bounds[0];
}
else
{
Compute_Translation_Transform(&Trans, Vector);
Transform_Box(Object, &Trans);
}
}
void Rotate_Box (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
TRANSFORM Trans;
Compute_Rotation_Transform(&Trans, Vector);
Transform_Box(Object, &Trans);
}
void Scale_Box (Object, Vector)
OBJECT *Object;
VECTOR *Vector;
{
BOX *Box = (BOX *)Object;
TRANSFORM Trans;
DBL temp;
if (((BOX *)Object)->Trans == NULL)
{
VEvaluateEq(Box->bounds[0], *Vector);
VEvaluateEq(Box->bounds[1], *Vector);
if (Box->bounds[0].x > Box->bounds[1].x) {
temp = Box->bounds[0].x;
Box->bounds[0].x = Box->bounds[1].x;
Box->bounds[1].x = temp;
}
if (Box->bounds[0].y > Box->bounds[1].y) {
temp = Box->bounds[0].y;
Box->bounds[0].y = Box->bounds[1].y;
Box->bounds[1].y = temp;
}
if (Box->bounds[0].z > Box->bounds[1].z) {
temp = Box->bounds[0].z;
Box->bounds[0].z = Box->bounds[1].z;
Box->bounds[1].z = temp;
}
Box->Bounds.Lower_Left = Box->bounds[0];
VSub(Object->Bounds.Lengths, Box->bounds[1], Box->bounds[0]);
}
else
{
Compute_Scaling_Transform(&Trans, Vector);
Transform_Box(Object, &Trans);
}
}
void Invert_Box (Object)
OBJECT *Object;
{
((BOX *)Object)->Inverted = 1 - ((BOX *)Object)->Inverted;
}
void Transform_Box (Object, Trans)
OBJECT *Object;
TRANSFORM *Trans;
{
BOX *box = (BOX *)Object;
if (box->Trans == NULL)
box->Trans = Create_Transform();
Compose_Transforms(box->Trans, Trans);
Object->Bounds.Lower_Left = box->bounds[0];
VSub(Object->Bounds.Lengths, box->bounds[1], box->bounds[0]);
recompute_bbox(&Object->Bounds, box->Trans);
}
BOX *Create_Box ()
{
BOX *New;
if ((New = (BOX *) malloc (sizeof (BOX))) == NULL)
MAError ("box");
INIT_OBJECT_FIELDS(New, BOX_OBJECT, &Box_Methods)
Make_Vector (&(New->bounds[0]), -1.0, -1.0, -1.0);
Make_Vector (&(New->bounds[1]), 1.0, 1.0, 1.0);
/* Recalculate the bounds */
Make_Vector(&New->Bounds.Lower_Left, -1.0, -1.0, -1.0);
Make_Vector(&New->Bounds.Lengths, 2.0, 2.0, 2.0);
/* Unlike HField, we don't always have a trans here */
New->Trans = NULL;
New->Inverted = FALSE;
return (New);
}
void Destroy_Box (Object)
OBJECT *Object;
{
Destroy_Transform(((BOX *)Object)->Trans);
free (Object);
}